package net.sf.rose.util;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import net.sf.rose.file.util.FileUtils;
import net.sf.rose.jdbc.PageBean;

public class QrCodeUtils {

    /**
     * 生成包含字符串信息的二维码图片
     * @param file        文件输出流路径
     * @param content     二维码携带信息
     * @param qrCodeSize  二维码图片大小
     * @param imageFormat 二维码图片的格式
     * @return 操作结果
     */
    public static PageBean createQrCode(File file, String content, int qrCodeSize, String imageFormat) {
        PageBean page = new PageBean();
        try {
            OutputStream outputStream = new FileOutputStream(file);
            // 设置二维码纠错级别MAP
            Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
            hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 矫错级别
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            // 创建比特矩阵(位矩阵)的QR码编码的字符串
            BitMatrix byteMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hintMap);
            // 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
            int matrixWidth = byteMatrix.getWidth();
            BufferedImage image = new BufferedImage(matrixWidth - 200, matrixWidth - 200, BufferedImage.TYPE_INT_RGB);
            image.createGraphics();
            Graphics2D graphics = (Graphics2D) image.getGraphics();
            graphics.setColor(Color.WHITE);
            graphics.fillRect(0, 0, matrixWidth, matrixWidth);
            // 使用比特矩阵画并保存图像
            graphics.setColor(Color.BLACK);
            for (int i = 0; i < matrixWidth; i++) {
                for (int j = 0; j < matrixWidth; j++) {
                    if (byteMatrix.get(i, j)) {
                        graphics.fillRect(i - 100, j - 100, 1, 1);
                    }
                }
            }
            page.setSuccess(ImageIO.write(image, imageFormat, outputStream));
        } catch (Exception e) {
            page.setSuccess(false);
            page.setMessage("生成二维码时出错了！" + e.getMessage());
        }
        return page;
    }

    /**
     * 读二维码并输出携带的信息
     * @param file 二维码图片文件
     * @return 操作结果
     */
    public static PageBean readQrCode(File file) {
        PageBean page = new PageBean();
        try {
            page = readQrCode(new FileInputStream(file));
        } catch (Exception e) {
            page.setSuccess(false);
            page.setMessage("生成二维码时出错了！" + e.getMessage());
        }
        return page;
    }

    /**
     * 读二维码并输出携带的信息
     * @param inputStream 二维码图片文件输入流
     * @return 操作结果
     */
    public static PageBean readQrCode(InputStream inputStream) {
        PageBean page = new PageBean();
        try {
            // 从输入流中获取字符串信息
            BufferedImage image = ImageIO.read(inputStream);
            // 将图像转换为二进制位图源
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            QRCodeReader reader = new QRCodeReader();
            Result result = null;
            try {
                result = reader.decode(bitmap);
            } catch (ReaderException e) {
                e.printStackTrace();
            }
            page.setData(result.getText());
        } catch (Exception e) {
            page.setSuccess(false);
            page.setMessage("生成二维码时出错了！" + e.getMessage());
        }
        return page;
    }

    /**
     * 读二维码并输出携带的信息
     * @param buf 二维码字节数组
     * @return 操作结果
     */
    public static PageBean readQrCode(byte[] buf) {
        PageBean page = new PageBean();
        try {
            InputStream inputStream = FileUtils.toInputStream(buf);
            page = readQrCode(inputStream);
        } catch (Exception e) {
            page.setSuccess(false);
            page.setMessage("生成二维码时出错了！" + e.getMessage());
        }
        return page;
    }

    /**
     * 测试代码
     * @param args 执行参数
     * @throws Exception 操作异常
     */
    public static void main(String[] args) throws Exception {
        // createQrCode(new File("d:\\qrcode.jpg"), "http://fgg047.natapp1.cc/any/wechat/suwei/redirectWxUrl.do?to_page=/weixin/index.html", 900, "JPEG");
        QrCodeUtil.generate("http://fgg047.natapp1.cc/any/wechat/suwei/redirectWxUrl.do?to_page=/weixin/index.html", 900, 900, FileUtil.file("d:/qrcode.jpg"));
        PageBean page = readQrCode(new FileInputStream(new File("d:\\qrcode.jpg")));
        System.out.println(page.getData().toString());

    }
}